import { CSGroup, IStreamlineData, ThickLine2 } from '@amcax/base';
import { ctx2, docMgr } from '@app-cad/module';
import { Picker3D, PickerMgr } from '@amcax/renderer';
import { Color, Vector2 } from 'three-legacy';
import { LineGeometry } from 'three-legacy/examples/jsm/lines/LineGeometry';

import { LineMaterial } from 'three-legacy/examples/jsm/lines/LineMaterial';
export const createModelInfo = (dxid: string, visibility: boolean) => {
  const docObjects = docMgr.flatDocumentObjects;

  const info = docObjects.find((obj) => {
    return obj.dxid === dxid;
  });
  const label = info?.label ?? '';
  const mark = info?.mark ?? [];
  const materials = info?.materials ?? { faces: [] };
  return {
    shape: dxid,
    dxid,
    label,
    materials,
    mark,
    children: [],
    sortid: 9,
    type: 'GeomBox',
    visibility: visibility,
  };
};

export function makeStreamlineMesh(
  item: IStreamlineData,
  colormap: number[][],
  scaler: number[],
  linewidth: number = 5,
  arrowlength: number = 1,
) {
  const mesh = new CSGroup(item.id);
  const points = item.points;
  const polylines = item.polylines;
  const arrows = item.arrows;

  const lineMaterial = new LineMaterial({
    linewidth: linewidth,
    vertexColors: true,
  });
  if (scaler.length <= 0 && points.length !== scaler.length) {
    lineMaterial.color = new Color(0x000000);
  }
  const vColors: number[] = [];
  scaler.forEach((item) => {
    vColors.push(...colormap[item]);
  });

  // 生成流线
  polylines?.forEach((polyline) => {
    const lineGeometry = new LineGeometry();
    const positions: number[] = [];
    const vertexColors: number[] = [];
    polyline.forEach((pointIndex) => {
      const point = points[pointIndex];
      positions.push(...points[pointIndex]);
      // TODO 二维坐标,应该需要根据参考系(基准面)计算出三维坐标
      if (point.length === 2) {
        positions.push(0);
      }
    });
    if (vColors.length > 0) {
      polyline.forEach((pointIndex) => {
        const start = pointIndex * 3;
        const end = start + 3; // 因为lineGeometry中color itemSize默认为3
        vertexColors.push(...vColors.slice(start, end));
      });
    }

    lineGeometry.setPositions(positions);
    if (vColors.length > 0) {
      lineGeometry.setColors(vertexColors); // 看了源码,color itemSize默认为3
    }
    const line = new ThickLine2(lineGeometry, lineMaterial);
    mesh.add(line);
  });

  // 生成箭头
  arrows?.forEach((arrow) => {
    if (arrow.length < 2) {
      return;
    }
    // arrow 有两个点的索引构成,使用这两个点构成一个向量
    const start = points[arrow[0]];
    const end = points[arrow[1]];
    const startV = new Vector2(start[0], start[1]);
    const endV = new Vector2(end[0], end[1]);
    const center = new Vector2(0, 0);
    const arrowVector = new Vector2().subVectors(endV, startV);
    // 计算出箭头的向量(与arrowVector的夹角是45度)
    const leftVector = arrowVector
      .clone()
      .rotateAround(center, Math.PI / 4)
      .setLength(arrowlength);
    const rightVector = arrowVector
      .clone()
      .rotateAround(center, -Math.PI / 4)
      .setLength(arrowlength);
    const arrowPoints = [
      new Vector2().subVectors(arrowVector, leftVector).add(startV).toArray(),
      end,
      new Vector2().subVectors(arrowVector, rightVector).add(startV).toArray(),
    ];
    const lineGeometry = new LineGeometry();
    const positions: number[] = arrowPoints
      .map((ap) => (ap.length === 2 ? [...ap, 0] : ap))
      .flat();
    const vertexColors: number[] = [];
    if (vColors.length > 0) {
      const start = arrow[1] * 3; // 都取end的颜色
      const end = start + 3; // 因为lineGeometry中color itemSize默认为3
      const endColor = vColors.slice(start, end);
      for (let i = 0; i < arrowPoints.length; i++) {
        vertexColors.push(...endColor);
      }
    }

    lineGeometry.setPositions(positions);
    lineGeometry.setColors(vertexColors); // 看了源码,color itemSize默认为3
    const line = new ThickLine2(lineGeometry, lineMaterial);
    mesh.add(line);
  });

  return mesh;
}

const clearStreamline = (streamlineIds) => {
  const picker = PickerMgr.getPicker<Picker3D>('3d');
  for (const id of streamlineIds) {
    const model = picker.getModelMesh(id);
    if (!model) {
      continue;
    }
    model.destroy();
  }
  ctx2.viewer.requestRender();
};

export const renderStreamlines = (
  data: IStreamlineData[],
  scaler: number[][],
  color_map: number[][][],
  streamlineIds: string[] = [],
) => {
  // const colormap = makeColorMap('jet');
  clearStreamline(streamlineIds);
  streamlineIds.length = 0;
  data.forEach((object: IStreamlineData, index) => {
    const mesh = makeStreamlineMesh(object, color_map[index], scaler[index]);
    mesh.addTo(ctx2.cadScene.meshGroup);
    streamlineIds.push(object.id);
  });
  ctx2.viewer.requestRender();
};
